package com.example.camerademo.camera1;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.example.camerademo.R;
import com.example.camerademo.camera1.utils.FileUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class CameraPic2Activity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static int mCameraID = Camera.CameraInfo.CAMERA_FACING_FRONT;
    private static int mCameraBackID = Camera.CameraInfo.CAMERA_FACING_BACK;
    private static int mOrientation = 0;
    private static int mOrientationBack = 0;

    SurfaceHolderCallbackFront surfaceHolderCallbackFront;
    private ImageView img;
    private CustomSurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;

    SurfaceHolderCallbackBack surfaceHolderCallbackBack;
    private ImageView imgBack;
    private CustomSurfaceView mSurfaceViewBack;
    private SurfaceHolder mSurfaceHolderBack;

    private Button btnFocus;
    private Button btnTakePic;
    private Button btnRestar;
    private Button btnChange;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_pic2);
        initView();

        mSurfaceHolder = mSurfaceView.getHolder();
        surfaceHolderCallbackFront = new SurfaceHolderCallbackFront();
        mSurfaceHolder.addCallback(surfaceHolderCallbackFront);


        //后置摄像头
        surfaceHolderCallbackBack = new SurfaceHolderCallbackBack();
        mSurfaceHolderBack = mSurfaceViewBack.getHolder();
        mSurfaceHolderBack.addCallback(surfaceHolderCallbackBack);

        initListener();
    }

    private void initListener() {

        btnFocus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraFocus(mCamera);
            }
        });
        btnRestar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mCamera != null) {
                    mCamera.startPreview();
                }
            }
        });
        btnChange.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchCamera();
            }
        });


        btnTakePic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (mCamera != null) {
                    mCamera.takePicture(null, null, new Camera.PictureCallback() {
                        @Override
                        public void onPictureTaken(byte[] data, Camera camera) {
                            // 获取Jpeg图片，并保存在sd卡上

                            String path = FileUtil.getCommonSavePath(CameraPic2Activity.this) + "/a_focus/";
                            System.out.println(".onPictureTaken path=" + path);

                            File pathDir = new File(path);
                            if (!pathDir.exists()) {
                                pathDir.mkdir();
                            }
                            File pictureFile = new File(path + "focusdemo.jpg");
                            if (pictureFile.exists()) {
                                pictureFile.delete();
                            }
                            try {
                                FileOutputStream fos = new FileOutputStream(pictureFile);
                                fos.write(data);
                                fos.close();
                            } catch (Exception e) {

                            }
                        }
                    });
                }


            }
        });


    }

    private void initView() {
        mSurfaceView = findViewById(R.id.surfaceview);
        img = findViewById(R.id.img);


        mSurfaceViewBack = findViewById(R.id.surfaceViewBack);
        imgBack = findViewById(R.id.imgBack);


        btnFocus = findViewById(R.id.focus);
        btnTakePic = findViewById(R.id.takepic);
        btnRestar = findViewById(R.id.restar);
        btnChange = findViewById(R.id.change);


    }


    private Camera mCamera;

    //获取相机数目：
    private void initCamera() {
        if (mCamera != null) {
            releaseCamera();
        }

        int numberOfCameras = Camera.getNumberOfCameras();
        System.out.println(TAG + ".initCamera numberOfCameras=" + numberOfCameras);
        mCamera = Camera.open(mCameraID);//open开启默认相机（后置相机）
        //后置相机和前置相机id常量：CameraInfo.CAMERA_FACING_BACK， CameraInfo.CAMERA_FACING_FRONT
        //mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        //mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        setCameraParameters(mCamera, 1);

        calculateCameraPreviewOrientation(this, mCameraID);

        mCamera.setDisplayOrientation(mOrientation);
        mCamera.startPreview();

        cameraFocus(mCamera);

    }

    private Camera mCameraBack;

    //获取相机数目：
    private void initCameraBack() {
        if (mCameraBack != null) {
            releaseCameraBack();
        }

        int numberOfCameras = Camera.getNumberOfCameras();
        System.out.println(TAG + ".initCamera numberOfCameras=" + numberOfCameras);
        mCameraBack = Camera.open(mCameraBackID);//open开启后置相机
        try {
            mCameraBack.setPreviewDisplay(mSurfaceHolderBack);
        } catch (IOException e) {
            e.printStackTrace();
        }
        setCameraParameters(mCameraBack, 2);

        calculateCameraPreviewOrientation(this, mCameraBackID);

        mCameraBack.setDisplayOrientation(mOrientationBack);
        mCameraBack.startPreview();

        cameraFocus(mCameraBack);

    }


    private class SurfaceHolderCallbackFront implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(@NonNull SurfaceHolder holder) {

        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            //当SurfaceView变化时也需要做相应操作，这里未做相应操作
            Log.i(TAG, "surfaceChanged: width=" + width);
            initCamera();
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

        }
    }

    private class SurfaceHolderCallbackBack implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(@NonNull SurfaceHolder holder) {

        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            initCameraBack();
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

        }
    }


    private ByteArrayOutputStream baos;
    byte[] imageByte;
    Bitmap bitmap;

    private void setCameraParameters(Camera mCamera, int cameraState) {
        Camera.Parameters parameters = mCamera.getParameters();
        //这里可以对camera进行一些参数设置

        parameters.setRecordingHint(true);
        //设置获取数据
        parameters.setPreviewFormat(ImageFormat.NV21);
        //parameters.setPreviewFormat(ImageFormat.YUV_420_888);

        //这个方法就会被调用一次
        /*mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                System.out.println(".onPreviewFrame 这个方法就会被调用一次");
                //这里面的Bytes的数据就是NV21格式的数据,或者YV12的数据
                getBitmap(data, camera);
            }
        });*/

        //通过setPreviewCallback方法监听预览的回调：
        mCamera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                //这里面的Bytes的数据就是NV21格式的数据,或者YUV_420_888的数据
                System.out.println(".onPreviewFrame");
                if (cameraState == 1) {
                    getBitmap(data, mCamera);
                } else if (cameraState == 2) {
                    getBitmapBack(data, mCamera);
                }

            }
        });
        mCamera.setParameters(parameters);
    }


    public void cameraFocus(Camera mCamera) {
        if (mCamera != null) {
            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean success, Camera camera) {
                    if (success) {
                        Toast.makeText(CameraPic2Activity.this, "对焦成功", Toast.LENGTH_SHORT).show();
                    } else {

                    }
                }
            });
        }
    }


    public void switchCamera() {
        if (mCameraID == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mCameraID = Camera.CameraInfo.CAMERA_FACING_FRONT;
        } else {
            mCameraID = Camera.CameraInfo.CAMERA_FACING_BACK;
        }
        try {
            initCamera();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getBitmap(byte[] data, Camera camera) {
        Camera.Size previewSize = camera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        YuvImage yuvimage = new YuvImage(
                data,
                ImageFormat.NV21,
                previewSize.width,
                previewSize.height,
                null);
        baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
        imageByte = baos.toByteArray();
        //将imageByte转换成bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        bitmap = BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length, options);

        if (mOrientation != 0) {
            // 旋转图片
            Matrix m = new Matrix();
            m.postRotate(mOrientation - 180);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
        }


        img.setImageBitmap(bitmap);
    }


    private void getBitmapBack(byte[] data, Camera camera) {
        Camera.Size previewSize = camera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        YuvImage yuvimage = new YuvImage(
                data,
                ImageFormat.NV21,
                previewSize.width,
                previewSize.height,
                null);
        baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
        imageByte = baos.toByteArray();
        //将imageByte转换成bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        bitmap = BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length, options);

        if (mOrientationBack != 0) {
            // 旋转图片
            Matrix m = new Matrix();
            m.postRotate(mOrientationBack - 180);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
        }


        imgBack.setImageBitmap(bitmap);
    }


    @Override
    protected void onResume() {
        super.onResume();
        if (mCamera != null) {
            mCamera.startPreview();
        }
        if (mCameraBack != null) {
            mCameraBack.startPreview();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.stopPreview();
        }
        if (mCameraBack != null) {
            mCameraBack.stopPreview();
        }
    }


    public void releaseCameraBack() {
        if (mCameraBack != null) {
            mSurfaceHolderBack.removeCallback(surfaceHolderCallbackBack);
            mCameraBack.setPreviewCallback(null);
            mCameraBack.stopPreview();
            mCameraBack.lock();
            mCameraBack.release();
            mCameraBack = null;
        }
    }


    public void releaseCamera() {
        if (mCamera != null) {
            mSurfaceHolder.removeCallback(surfaceHolderCallbackFront);
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.lock();
            mCamera.release();
            mCamera = null;
        }
    }


    /**
     * 设置预览角度，setDisplayOrientation本身只能改变预览的角度
     * previewFrameCallback以及拍摄出来的照片是不会发生改变的，拍摄出来的照片角度依旧不正常的
     * 拍摄的照片需要自行处理
     * 这里Nexus5X的相机简直没法吐槽，后置摄像头倒置了，切换摄像头之后就出现问题了。
     *
     * @param activity
     */
    public int calculateCameraPreviewOrientation(Activity activity, int cameraId) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();

        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }

        if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mOrientation = result;
        } else {
            mOrientationBack = result;
        }


        System.out.println("=========orienttaion=============" + result);
        return result;
    }


}